/*
 * Copyright (C) 2005 - 2013 MaNGOS <http://www.getmangos.com/>
 *
 * Copyright (C) 2008 - 2013 Trinity <http://www.trinitycore.org/>
 *
 * Copyright (C) 2010 - 2013 ProjectSkyfire <http://www.projectskyfire.org/>
 *
 * Copyright (C) 2011 - 2013 ArkCORE <http://www.arkania.net/>
 *
 * This program is free software; you can redistribute it and/or modify
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef ARKCORE_SMARTSCRIPTMGR_H
#define ARKCORE_SMARTSCRIPTMGR_H

#include "Common.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "Unit.h"
#include "ConditionMgr.h"
#include "CreatureTextMgr.h"
#include "Spell.h"
#include "DB2Stores.h"

//#include "SmartScript.h"
//#include "SmartAI.h"

struct WayPoint
{
    WayPoint(uint32 _id, float _x, float _y, float _z)
    {
        id = _id;
        x = _x;
        y = _y;
        z = _z;
    }

    uint32 id;
    float x;
    float y;
    float z;
};

enum SMART_EVENT_PHASE
{
    SMART_EVENT_PHASE_ALWAYS = 0, SMART_EVENT_PHASE_1 = 1, SMART_EVENT_PHASE_2 = 2, SMART_EVENT_PHASE_3 = 3, SMART_EVENT_PHASE_4 = 4, SMART_EVENT_PHASE_5 = 5, SMART_EVENT_PHASE_6 = 6, SMART_EVENT_PHASE_MAX = 7,

    SMART_EVENT_PHASE_COUNT = 6,
};

enum SMART_EVENT_PHASE_BITS
{
    SMART_EVENT_PHASE_ALWAYS_BIT = 0, SMART_EVENT_PHASE_1_BIT = 1, SMART_EVENT_PHASE_2_BIT = 2, SMART_EVENT_PHASE_3_BIT = 4, SMART_EVENT_PHASE_4_BIT = 8, SMART_EVENT_PHASE_5_BIT = 16, SMART_EVENT_PHASE_6_BIT = 32, SMART_EVENT_PHASE_ALL = SMART_EVENT_PHASE_1_BIT + SMART_EVENT_PHASE_2_BIT + SMART_EVENT_PHASE_3_BIT + SMART_EVENT_PHASE_4_BIT + SMART_EVENT_PHASE_5_BIT + SMART_EVENT_PHASE_6_BIT,
};

const uint32 SmartPhaseMask[SMART_EVENT_PHASE_COUNT][2] =
{
{ SMART_EVENT_PHASE_1, SMART_EVENT_PHASE_1_BIT },
{ SMART_EVENT_PHASE_2, SMART_EVENT_PHASE_2_BIT },
{ SMART_EVENT_PHASE_3, SMART_EVENT_PHASE_3_BIT },
{ SMART_EVENT_PHASE_4, SMART_EVENT_PHASE_4_BIT },
{ SMART_EVENT_PHASE_5, SMART_EVENT_PHASE_5_BIT },
{ SMART_EVENT_PHASE_6, SMART_EVENT_PHASE_6_BIT }, };

enum SMART_EVENT
{
    SMART_EVENT_UPDATE_IC = 0,          //1             // InitialMin, InitialMax, RepeatMin, RepeatMax
    SMART_EVENT_UPDATE_OOC = 1,          //1             // InitialMin, InitialMax, RepeatMin, RepeatMax
    SMART_EVENT_HEALT_PCT = 2,          //1             // HPMin%, HPMax%,  RepeatMin, RepeatMax
    SMART_EVENT_MANA_PCT = 3,          //1             // ManaMin%, ManaMax%, RepeatMin, RepeatMax
    SMART_EVENT_AGGRO = 4,          //1             // NONE
    SMART_EVENT_KILL = 5,          //1             // CooldownMin0, CooldownMax1, playerOnly2, else creature entry3
    SMART_EVENT_DEATH = 6,          //1             // NONE
    SMART_EVENT_EVADE = 7,          //1             // NONE
    SMART_EVENT_SPELLHIT = 8,          //1             // SpellID, School, CooldownMin, CooldownMax
    SMART_EVENT_RANGE = 9,          //1             // MinDist, MaxDist, RepeatMin, RepeatMax
    SMART_EVENT_OOC_LOS = 10,          //1             // NoHostile, MaxRnage, CooldownMin, CooldownMax
    SMART_EVENT_RESPAWN = 11,          //1             // type, MapId, ZoneId
    SMART_EVENT_TARGET_HEALTH_PCT = 12,          //1             // HPMin%, HPMax%, RepeatMin, RepeatMax
    SMART_EVENT_TARGET_CASTING = 13,          //1             // RepeatMin, RepeatMax
    SMART_EVENT_FRIENDLY_HEALTH = 14,          //1             // HPDeficit, Radius, RepeatMin, RepeatMax
    SMART_EVENT_FRIENDLY_IS_CC = 15,          //1             // Radius, RepeatMin, RepeatMax
    SMART_EVENT_FRIENDLY_MISSING_BUFF = 16,          //1             // SpellId, Radius, RepeatMin, RepeatMax
    SMART_EVENT_SUMMONED_UNIT = 17,          //1             // CreatureId(0 all), CooldownMin, CooldownMax
    SMART_EVENT_TARGET_MANA_PCT = 18,          //1             // ManaMin%, ManaMax%, RepeatMin, RepeatMax
    SMART_EVENT_ACCEPTED_QUEST = 19,          //1             // QuestID(0any)
    SMART_EVENT_REWARD_QUEST = 20,          //1             // QuestID(0any)
    SMART_EVENT_REACHED_HOME = 21,          //1             // NONE
    SMART_EVENT_RECEIVE_EMOTE = 22,          //1             // EmoteId, CooldownMin, CooldownMax, condition, val1, val2, val3
    SMART_EVENT_HAS_AURA = 23,          //1             // Param1 = SpellID, Param2 = Number of Time STacked, Param3/4 RepeatMin, RepeatMax
    SMART_EVENT_TARGET_BUFFED = 24,          //1             // Param1 = SpellID, Param2 = Number of Time STacked, Param3/4 RepeatMin, RepeatMax
    SMART_EVENT_RESET = 25,          //1             // Called after combat, when the creature respawn and spawn.

    SMART_EVENT_IC_LOS = 26,          //1             // NoHostile, MaxRnage, CooldownMin, CooldownMax
    SMART_EVENT_PASSENGER_BOARDED = 27,          //1             // CooldownMin, CooldownMax
    SMART_EVENT_PASSENGER_REMOVED = 28,          //1             // CooldownMin, CooldownMax
    SMART_EVENT_CHARMED = 29,          //1             // NONE
    SMART_EVENT_CHARMED_TARGET = 30,          //1             // NONE
    SMART_EVENT_SPELLHIT_TARGET = 31,          //1             // SpellID, School, CooldownMin, CooldownMax
    SMART_EVENT_DAMAGED = 32,          //1             // MinDmg, MaxDmg, CooldownMin, CooldownMax
    SMART_EVENT_DAMAGED_TARGET = 33,          //1             // MinDmg, MaxDmg, CooldownMin, CooldownMax
    SMART_EVENT_MOVEMENTINFORM = 34,          //1             // MovementType(any), PointID
    SMART_EVENT_SUMMON_DESPAWNED = 35,          //1             // Entry, CooldownMin, CooldownMax
    SMART_EVENT_CORPSE_REMOVED = 36,          //1             // NONE
    SMART_EVENT_AI_INIT = 37,          //1             // NONE
    SMART_EVENT_DATA_SET = 38,          //1             // Id, Value, CooldownMin, CooldownMax
    SMART_EVENT_WAYPOINT_START = 39,          //1             // PointId(0any), pathID(0any)
    SMART_EVENT_WAYPOINT_REACHED = 40,          //1             // PointId(0any), pathID(0any)
    SMART_EVENT_TRANSPORT_ADDPLAYER = 41,          //1             // NONE
    SMART_EVENT_TRANSPORT_ADDCREATURE = 42,          //1             // Entry (0 any)
    SMART_EVENT_TRANSPORT_REMOVE_PLAYER = 43,          //1             // NONE
    SMART_EVENT_TRANSPORT_RELOCATE = 44,          //1             // PointId
    SMART_EVENT_INSTANCE_PLAYER_ENTER = 45,          //1             // Team (0 any), CooldownMin, CooldownMax
    SMART_EVENT_AREATRIGGER_ONTRIGGER = 46,          //1             // TriggerId(0 any)
    SMART_EVENT_QUEST_ACCEPTED = 47,          //1             // none
    SMART_EVENT_QUEST_OBJ_COPLETETION = 48,          //1             // none
    SMART_EVENT_QUEST_COMPLETION = 49,          //1             // none
    SMART_EVENT_QUEST_REWARDED = 50,          //1             // none
    SMART_EVENT_QUEST_FAIL = 51,          //1             // none
    SMART_EVENT_TEXT_OVER = 52,          //1             // GroupId from creature_text,  creature entry who talks (0 any)
    SMART_EVENT_RECEIVE_HEAL = 53,          //1             // MinHeal, MaxHeal, CooldownMin, CooldownMax
    SMART_EVENT_JUST_SUMMONED = 54,          //1             // none
    SMART_EVENT_WAYPOINT_PAUSED = 55,          //1             // PointId(0any), pathID(0any)
    SMART_EVENT_WAYPOINT_RESUMED = 56,          //1             // PointId(0any), pathID(0any)
    SMART_EVENT_WAYPOINT_STOPPED = 57,          //1             // PointId(0any), pathID(0any)
    SMART_EVENT_WAYPOINT_ENDED = 58,          //1             // PointId(0any), pathID(0any)
    SMART_EVENT_TIMED_EVENT_TRIGGERED = 59,          //1             // id
    SMART_EVENT_UPDATE = 60,          //1             // InitialMin, InitialMax, RepeatMin, RepeatMax
    SMART_EVENT_LINK = 61,          //1             // INTERNAL USAGE, no params, used to link together multiple events, does not use any extra resources to iterate event lists needlessly
    SMART_EVENT_GOSSIP_SELECT = 62,          //1             // menuID, actionID
    SMART_EVENT_JUST_CREATED = 63,          //1             // none
    SMART_EVENT_GOSSIP_HELLO = 64,          //1             // none
    SMART_EVENT_FOLLOW_COMPLETED = 65,          //1             // none
    SMART_EVENT_DUMMY_EFFECT = 66,          //1             // spellId, effectIndex
    SMART_EVENT_IS_BEHIND_TARGET = 67,          //1             // cooldownMin, CooldownMax

    SMART_EVENT_END = 68,
};

struct SmartEvent
{
    SMART_EVENT type;
    uint32 event_phase_mask;
    uint32 event_chance;
    uint32 event_flags;
    union
    {
        struct
        {
            uint32 min;
            uint32 max;
            uint32 repeatMin;
            uint32 repeatMax;
        } minMaxRepeat;

        struct
        {
            uint32 cooldownMin;
            uint32 cooldownMax;
            uint32 playerOnly;
            uint32 creature;
        } kill;

        struct
        {
            uint32 spell;
            uint32 school;
            uint32 cooldownMin;
            uint32 cooldownMax;
        } spellHit;

        struct
        {
            uint32 noHostile;
            uint32 maxDist;
            uint32 cooldownMin;
            uint32 cooldownMax;
        } los;

        struct
        {
            uint32 type;
            uint32 map;
            uint32 area;
        } respawn;

        struct
        {
            uint32 repeatMin;
            uint32 repeatMax;
        } minMax;

        struct
        {
            uint32 hpDeficit;
            uint32 radius;
            uint32 repeatMin;
            uint32 repeatMax;
        } friendlyHealt;

        struct
        {
            uint32 radius;
            uint32 repeatMin;
            uint32 repeatMax;
        } friendlyCC;

        struct
        {
            uint32 spell;
            uint32 radius;
            uint32 repeatMin;
            uint32 repeatMax;
        } missingBuff;

        struct
        {
            uint32 creature;
            uint32 cooldownMin;
            uint32 cooldownMax;
        } summoned;

        struct
        {
            uint32 quest;
        } quest;

        struct
        {
            uint32 emote;
            uint32 cooldownMin;
            uint32 cooldownMax;
        } emote;

        struct
        {
            uint32 spell;
            uint32 count;
            uint32 repeatMin;
            uint32 repeatMax;
        } aura;

        struct
        {
            uint32 spell;
            uint32 count;
            uint32 repeatMin;
            uint32 repeatMax;
        } targetAura;

        struct
        {
            uint32 type;
            uint32 id;
        } movementInform;

        struct
        {
            uint32 id;
            uint32 value;
            uint32 cooldownMin;
            uint32 cooldownMax;
        } dataSet;

        struct
        {
            uint32 pointID;
            uint32 pathID;
        } waypoint;

        struct
        {
            uint32 creature;
        } transportAddCreature;

        struct
        {
            uint32 pointID;
        } transportRelocate;

        struct
        {
            uint32 team;
            uint32 cooldownMin;
            uint32 cooldownMax;
        } instancePlayerEnter;

        struct
        {
            uint32 id;
        } areatrigger;

        struct
        {
            uint32 textGroupID;
            uint32 creatureEntry;
        } textOver;

        struct
        {
            uint32 id;
        } timedEvent;

        struct
        {
            uint32 sender;
            uint32 action;
        } gossip;

        struct
        {
            uint32 spell;
            uint32 effIndex;
        } dummy;

        struct
        {
            uint32 cooldownMin;
            uint32 cooldownMax;
        } behindTarget;

        struct
        {
            uint32 param1;
            uint32 param2;
            uint32 param3;
            uint32 param4;
        } raw;
    };
};

enum SMART_SCRIPT_RESPAWN_CONDITION
{
    SMART_SCRIPT_RESPAWN_CONDITION_NONE = 0, SMART_SCRIPT_RESPAWN_CONDITION_MAP = 1, SMART_SCRIPT_RESPAWN_CONDITION_AREA = 2, SMART_SCRIPT_RESPAWN_CONDITION_END = 3,
};

enum SMART_ACTION
{
    SMART_ACTION_NONE = 0,          // No action
    SMART_ACTION_TALK = 1,          // groupID from creature_text, duration to wait before TEXT_OVER event is triggered
    SMART_ACTION_SET_FACTION = 2,          // FactionId (or 0 for default)
    SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL = 3,          // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph)
    SMART_ACTION_SOUND = 4,          // SoundId, TextRange
    SMART_ACTION_PLAY_EMOTE = 5,          // EmoteId
    SMART_ACTION_FAIL_QUEST = 6,          // QuestID
    SMART_ACTION_ADD_QUEST = 7,          // QuestID
    SMART_ACTION_SET_REACT_STATE = 8,          // state
    SMART_ACTION_ACTIVATE_GOBJECT = 9,          //
    SMART_ACTION_RANDOM_EMOTE = 10,          // EmoteId1, EmoteId2, EmoteId3...
    SMART_ACTION_CAST = 11,          // SpellId, CastFlags
    SMART_ACTION_SUMMON_CREATURE = 12,          // CreatureID, summonType, duration in ms, storageID, attackInvoker,
    SMART_ACTION_THREAT_SINGLE_PCT = 13,          // Threat%
    SMART_ACTION_THREAT_ALL_PCT = 14,          // Threat%
    SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS = 15,          // QuestID
    SMART_ACTION_SEND_CASTCREATUREORGO = 16,          // QuestID, SpellId
    SMART_ACTION_SET_EMOTE_STATE = 17,          // emoteID
    SMART_ACTION_SET_UNIT_FLAG = 18,          // Flags (may be more than one field OR'd together), Target
    SMART_ACTION_REMOVE_UNIT_FLAG = 19,          // Flags (may be more than one field OR'd together), Target
    SMART_ACTION_AUTO_ATTACK = 20,          // AllowAttackState (0 = stop attack, anything else means continue attacking)
    SMART_ACTION_ALLOW_COMBAT_MOVEMENT = 21,          // AllowCombatMovement (0 = stop combat based movement, anything else continue attacking)
    SMART_ACTION_SET_EVENT_PHASE = 22,          // Phase
    SMART_ACTION_INC_EVENT_PHASE = 23,          // Value (may be negative to decrement phase, should not be 0)
    SMART_ACTION_EVADE = 24,          // No Params
    SMART_ACTION_FLEE_FOR_ASSIST = 25,          // No Params
    SMART_ACTION_CALL_GROUPEVENTHAPPENS = 26,          // QuestID
    SMART_ACTION_CALL_CASTEDCREATUREORGO = 27,          // CreatureId, SpellId
    SMART_ACTION_REMOVEAURASFROMSPELL = 28,          // Spellid
    SMART_ACTION_FOLLOW = 29,          // Distance, Angle, EndCreatureEntry, credit, creditType (0monsterkill, 1event)
    SMART_ACTION_RANDOM_PHASE = 30,          // PhaseId1, PhaseId2, PhaseId3...
    SMART_ACTION_RANDOM_PHASE_RANGE = 31,          // PhaseMin, PhaseMax
    SMART_ACTION_RESET_GOBJECT = 32,          //
    SMART_ACTION_CALL_KILLEDMONSTER = 33,          // CreatureId,
    SMART_ACTION_SET_INST_DATA = 34,          // Field, Data
    SMART_ACTION_SET_INST_DATA64 = 35,          // Field,
    SMART_ACTION_UPDATE_TEMPLATE = 36,          // Entry, Team
    SMART_ACTION_DIE = 37,          // No Params
    SMART_ACTION_SET_IN_COMBAT_WITH_ZONE = 38,          // No Params
    SMART_ACTION_CALL_FOR_HELP = 39,          // Radius
    SMART_ACTION_SET_SHEATH = 40,          // Sheath (0-unarmed, 1-melee, 2-ranged)
    SMART_ACTION_FORCE_DESPAWN = 41,          // timer
    SMART_ACTION_SET_INVINCIBILITY_HP_LEVEL = 42,          // MinHpValue(+pct, -flat)
    SMART_ACTION_MOUNT_TO_ENTRY_OR_MODEL = 43,          // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to unmount)
    SMART_ACTION_SET_INGAME_PHASE_MASK = 44,          // mask

    SMART_ACTION_SET_DATA = 45,          // Field, Data (only creature TODO)
    SMART_ACTION_MOVE_FORWARD = 46,          // distance
    SMART_ACTION_SET_VISIBILITY = 47,          // on/off
    SMART_ACTION_SET_ACTIVE = 48,          // No Params
    SMART_ACTION_ATTACK_START = 49,          //
    SMART_ACTION_SUMMON_GO = 50,          // GameObjectID, DespawnTime in ms,
    SMART_ACTION_KILL_UNIT = 51,          //
    SMART_ACTION_ACTIVATE_TAXI = 52,          // TaxiID
    SMART_ACTION_WP_START = 53,          // run/walk, pathID, canRepeat, quest, despawntime, reactState
    SMART_ACTION_WP_PAUSE = 54,          // time
    SMART_ACTION_WP_STOP = 55,          // despawnTime, quest, fail?
    SMART_ACTION_ADD_ITEM = 56,          // itemID, count
    SMART_ACTION_REMOVE_ITEM = 57,          // itemID, count
    SMART_ACTION_INSTALL_AI_TEMPLATE = 58,          // AITemplateID
    SMART_ACTION_SET_RUN = 59,          // 0/1
    SMART_ACTION_SET_FLY = 60,          // 0/1
    SMART_ACTION_SET_SWIMM = 61,          // 0/1
    SMART_ACTION_TELEPORT = 62,          // mapID,
    SMART_ACTION_STORE_VARIABLE_DECIMAL = 63,          // varID, number
    SMART_ACTION_STORE_TARGET_LIST = 64,          // varID,
    SMART_ACTION_WP_RESUME = 65,          // none
    SMART_ACTION_SET_ORIENTATION = 66,          //

    SMART_ACTION_CREATE_TIMED_EVENT = 67,          // id, InitialMin, InitialMax, RepeatMin(only if it repeats), RepeatMax(only if it repeats), chance
    SMART_ACTION_PLAYMOVIE = 68,          // entry
    SMART_ACTION_MOVE_TO_POS = 69,          // xyz
    SMART_ACTION_RESPAWN_TARGET = 70,          //
    SMART_ACTION_EQUIP = 71,          // entry, slotmask slot1, slot2, slot3   , only slots with mask set will be sent to client, bits are 1, 2, 4, leaving mask 0 is defaulted to mask 7 (send all), slots1-3 are only used if no entry is set
    SMART_ACTION_CLOSE_GOSSIP = 72,          // none
    SMART_ACTION_TRIGGER_TIMED_EVENT = 73,          // id(>1)
    SMART_ACTION_REMOVE_TIMED_EVENT = 74,          // id(>1)
    SMART_ACTION_ADD_AURA = 75,          // spellid,  targets
    SMART_ACTION_OVERRIDE_SCRIPT_BASE_OBJECT = 76,          // WARNING: CAN CRASH CORE, do not use if you dont know what you are doing
    SMART_ACTION_RESET_SCRIPT_BASE_OBJECT = 77,          // none
    SMART_ACTION_CALL_SCRIPT_RESET = 78,          // none
    SMART_ACTION_ENTER_VEHICLE = 79,          // seatID
    SMART_ACTION_CALL_TIMED_ACTIONLIST = 80,          // ID (overwrites already running actionlist), stop after combat?(0/1), timer update type(0-OOC, 1-IC, 2-ALWAYS)
    SMART_ACTION_SET_NPC_FLAG = 81,          // Flags
    SMART_ACTION_ADD_NPC_FLAG = 82,          // Flags
    SMART_ACTION_REMOVE_NPC_FLAG = 83,          // Flags
    SMART_ACTION_SIMPLE_TALK = 84,          // groupID, can be used to make players say groupID, Text_over event is not triggered, whisper can not be used (Target units will say the text)
    SMART_ACTION_INVOKER_CAST = 85,          // spellID, castFlags,   if avaliable, last used invoker will cast spellId with castFlags on targets
    SMART_ACTION_CROSS_CAST = 86,          // spellID, castFlags, CasterTargetType, CasterTarget param1, CasterTarget param2, CasterTarget param3, ( + the origonal target fields as Destination target),   CasterTargets will cast spellID on all Targets (use with caution if targeting multiple * multiple units)
    SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST = 87,          // script9 ids 1-9
    SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST = 88,          // script9 id min, max
    SMART_ACTION_RANDOM_MOVE = 89,          // maxDist

    SMART_ACTION_SET_UNIT_FIELD_BYTES_1 = 90,          // bytes, target
    SMART_ACTION_REMOVE_UNIT_FIELD_BYTES_1 = 91,          // bytes, target

    SMART_ACTION_INTERRUPT_SPELL = 92,

    SMART_ACTION_SEND_GO_CUSTOM_ANIM = 93,          // anim id

    SMART_ACTION_SET_DYNAMIC_FLAG = 94,          // Flags
    SMART_ACTION_ADD_DYNAMIC_FLAG = 95,          // Flags
    SMART_ACTION_REMOVE_DYNAMIC_FLAG = 96,          // Flags
    SMART_ACTION_SEND_GOSSIP_MENU = 98,          // menuId, optionId

    SMART_ACTION_END = 99,
};

struct SmartAction
{
    SMART_ACTION type;

    union
    {
        struct
        {
            uint32 textGroupID;
            uint32 duration;
        } talk;

        struct
        {
            uint32 factionID;
        } faction;

        struct
        {
            uint32 creature;
            uint32 model;
        } morphOrMount;

        struct
        {
            uint32 sound;
            uint32 range;
        } sound;

        struct
        {
            uint32 emote;
        } emote;

        struct
        {
            uint32 quest;
        } quest;

        struct
        {
            uint32 state;
        } react;

        struct
        {
            uint32 emote1;
            uint32 emote2;
            uint32 emote3;
            uint32 emote4;
            uint32 emote5;
            uint32 emote6;
        } randomEmote;

        struct
        {
            uint32 spell;
            uint32 flags;
            uint32 targetType;
            uint32 targetParam1;
            uint32 targetParam2;
            uint32 targetParam3;
        } cast;

        struct
        {
            uint32 creature;
            uint32 type;
            uint32 duration;
            uint32 storageID;
            uint32 attackInvoker;
        } summonCreature;

        struct
        {
            uint32 threatINC;
            uint32 threatDEC;
        } threatPCT;

        struct
        {
            uint32 quest;
            uint32 spell;
        } castCreatureOrGO;

        struct
        {
            uint32 flag1;
            uint32 flag2;
            uint32 flag3;
            uint32 flag4;
            uint32 flag5;
            uint32 flag6;
        } addUnitFlag;

        struct
        {
            uint32 flag1;
            uint32 flag2;
            uint32 flag3;
            uint32 flag4;
            uint32 flag5;
            uint32 flag6;
        } removeUnitFlag;

        struct
        {
            uint32 attack;
        } autoAttack;

        struct
        {
            uint32 move;
        } combatMove;

        struct
        {
            uint32 phase;
        } setEventPhase;

        struct
        {
            uint32 inc;
            uint32 dec;
        } incEventPhase;

        struct
        {
            uint32 creature;
            uint32 spell;
        } castedCreatureOrGO;

        struct
        {
            uint32 spell;
        } removeAura;

        struct
        {
            uint32 dist;
            uint32 angle;
            uint32 entry;
            uint32 credit;
            uint32 creditType;
        } follow;

        struct
        {
            uint32 phase1;
            uint32 phase2;
            uint32 phase3;
            uint32 phase4;
            uint32 phase5;
            uint32 phase6;
        } randomPhase;

        struct
        {
            uint32 phaseMin;
            uint32 phaseMax;
        } randomPhaseRange;

        struct
        {
            uint32 creature;
        } killedMonster;

        struct
        {
            uint32 field;
            uint32 data;
        } setInstanceData;

        struct
        {
            uint32 field;
        } setInstanceData64;

        struct
        {
            uint32 creature;
            uint32 team;
        } updateTemplate;

        struct
        {
            uint32 range;
        } callHelp;

        struct
        {
            uint32 sheath;
        } setSheath;

        struct
        {
            uint32 delay;
        } forceDespawn;

        struct
        {
            uint32 minHP;
            uint32 percent;
        } invincHP;

        struct
        {
            uint32 mask;
        } ingamePhaseMask;

        struct
        {
            uint32 field;
            uint32 data;
        } setData;

        struct
        {
            uint32 distance;
        } moveRandom;

        struct
        {
            uint32 state;
        } visibility;

        struct
        {
            uint32 entry;
            uint32 despawnTime;
        } summonGO;

        struct
        {
            uint32 id;
        } taxi;

        struct
        {
            uint32 run;
            uint32 pathID;
            uint32 repeat;
            uint32 quest;
            uint32 despawnTime;
            uint32 reactState;
        } wpStart;

        struct
        {
            uint32 delay;
        } wpPause;

        struct
        {
            uint32 despawnTime;
            uint32 quest;
            uint32 fail;
        } wpStop;

        struct
        {
            uint32 entry;
            uint32 count;
        } item;

        struct
        {
            uint32 id;
            uint32 param1;
            uint32 param2;
            uint32 param3;
            uint32 param4;
            uint32 param5;
        } installTtemplate;

        struct
        {
            uint32 run;
        } setRun;

        struct
        {
            uint32 fly;
        } setFly;

        struct
        {
            uint32 swimm;
        } setSwimm;

        struct
        {
            uint32 mapID;
        } teleport;

        struct
        {
            uint32 id;
            uint32 number;
        } storeVar;

        struct
        {
            uint32 id;
        } storeTargets;

        struct
        {
            uint32 id;
            uint32 min;
            uint32 max;
            uint32 repeatMin;
            uint32 repeatMax;
            uint32 chance;
        } timeEvent;

        struct
        {
            uint32 entry;
        } movie;

        struct
        {
            uint32 entry;
            uint32 mask;
            uint32 slot1;
            uint32 slot2;
            uint32 slot3;
        } equip;

        struct
        {
            uint32 flag;
        } unitFlag;

        struct
        {
            uint32 byte1;
        } setunitByte;

        struct
        {
            uint32 byte1;
        } delunitByte;

        struct
        {
            uint32 seat;
        } enterVehicle;

        struct
        {
            uint32 id;
            uint32 dontResume;
            uint32 timerType;
        } timedActionList;

        struct
        {
            uint32 entry1;
            uint32 entry2;
            uint32 entry3;
            uint32 entry4;
            uint32 entry5;
            uint32 entry6;
        } randTimedActionList;

        struct
        {
            bool withDelayed;
            uint32 spell_id;
            bool withInstant;
        } interruptSpellCasting;

        struct
        {
            uint32 anim;
        } sendGoCustomAnim;
        struct
        {
            uint32 gossipMenuId;
            uint32 gossipNpcTextId;
        } sendGossipMenu;
        struct
        {
            uint32 param1;
            uint32 param2;
            uint32 param3;
            uint32 param4;
            uint32 param5;
            uint32 param6;
        } raw;
    };
};

enum SMARTAI_TEMPLATE
{
    SMARTAI_TEMPLATE_BASIC = 0,          //nothing is preset
    SMARTAI_TEMPLATE_CASTER = 1,          //spellid, repeatMin, repeatMax, range, manaPCT +JOIN: target_param1 as castFlag
    SMARTAI_TEMPLATE_TURRET = 2,          //spellid, repeatMin, repeatMax +JOIN: target_param1 as castFlag
    SMARTAI_TEMPLATE_PASSIVE = 3, SMARTAI_TEMPLATE_CAGED_GO_PART = 4,          //creatureID, give credit at point end?,
    SMARTAI_TEMPLATE_CAGED_NPC_PART = 5,          //gameObjectID, despawntime, run?, dist, TextGroupID
    SMARTAI_TEMPLATE_END = 6,
};

enum SMARTAI_TARGETS
{
    SMART_TARGET_NONE = 0,          // NONE, defaulting to invoket
    SMART_TARGET_SELF = 1,          // Self cast
    SMART_TARGET_VICTIM = 2,          // Our current target (ie: highest aggro)
    SMART_TARGET_HOSTILE_SECOND_AGGRO = 3,          // Second highest aggro
    SMART_TARGET_HOSTILE_LAST_AGGRO = 4,          // Dead last on aggro
    SMART_TARGET_HOSTILE_RANDOM = 5,          // Just any random target on our threat list
    SMART_TARGET_HOSTILE_RANDOM_NOT_TOP = 6,          // Any random target except top threat
    SMART_TARGET_ACTION_INVOKER = 7,          // Unit who caused this Event to occur
    SMART_TARGET_POSITION = 8,          // use xyz from event params
    SMART_TARGET_CREATURE_RANGE = 9,          // CreatureEntry(0any), minDist, maxDist
    SMART_TARGET_CREATURE_GUID = 10,          // guid, entry
    SMART_TARGET_CREATURE_DISTANCE = 11,          // CreatureEntry(0any), maxDist
    SMART_TARGET_STORED = 12,          // id, uses pre-stored target(list)
    SMART_TARGET_GAMEOBJECT_RANGE = 13,          // entry(0any), min, max
    SMART_TARGET_GAMEOBJECT_GUID = 14,          // guid, entry
    SMART_TARGET_GAMEOBJECT_DISTANCE = 15,          // entry(0any), maxDist
    SMART_TARGET_INVOKER_PARTY = 16,          // invoker's party members
    SMART_TARGET_PLAYER_RANGE = 17,          // min, max
    SMART_TARGET_PLAYER_DISTANCE = 18,          // maxDist
    SMART_TARGET_CLOSEST_CREATURE = 19,          // CreatureEntry(0any)
    SMART_TARGET_CLOSEST_GAMEOBJECT = 20,          // entry(0any)
    SMART_TARGET_CLOSEST_PLAYER = 21,          // none
    SMART_TARGET_ACTION_INVOKER_VEHICLE = 22,          // Unit's vehicle who caused this Event to occur
    SMART_TARGET_OWNER_OR_SUMMONER = 23,          // Unit's owner or summoner
    SMART_TARGET_THREAT_LIST = 24,          // All units on creature's threat list
    SMART_TARGET_END = 25,
};

struct SmartTarget
{
    SmartTarget(SMARTAI_TARGETS t = SMART_TARGET_NONE, uint32 p1 = 0, uint32 p2 = 0, uint32 p3 = 0)
    {
        type = t;
        raw.param1 = p1;
        raw.param2 = p2;
        raw.param3 = p3;
    }
    SMARTAI_TARGETS type;
    float x, y, z, o;
    union
    {
        struct
        {
            uint32 creature;
            uint32 minDist;
            uint32 maxDist;
        } unitRange;

        struct
        {
            uint32 guid;
            uint32 entry;
        } unitGUID;

        struct
        {
            uint32 creature;
            uint32 dist;
        } unitDistance;

        struct
        {
            uint32 dist;
        } playerDistance;

        struct
        {
            uint32 minDist;
            uint32 maxDist;
        } playerRange;

        struct
        {
            uint32 id;
        } stored;

        struct
        {
            uint32 entry;
            uint32 minDist;
            uint32 maxDist;
        } goRange;

        struct
        {
            uint32 guid;
            uint32 entry;
        } goGUID;

        struct
        {
            uint32 entry;
            uint32 dist;
        } goDistance;

        struct
        {
            uint32 map;
        } position;

        struct
        {
            uint32 entry;
            uint32 dist;
            uint32 dead;
        } closest;

        struct
        {
            uint32 param1;
            uint32 param2;
            uint32 param3;
        } raw;
    };
};

enum eSmartAI
{
    SMART_EVENT_PARAM_COUNT = 4, SMART_ACTION_PARAM_COUNT = 6, SMART_SUMMON_COUNTER = 0xFFFFFF, SMART_ESCORT_LAST_OOC_POINT = 0xFFFFFF, SMART_RANDOM_POINT = 0xFFFFFE, SMART_ESCORT_TARGETS = 0xFFFFFF
};

enum SmartScriptType
{
    SMART_SCRIPT_TYPE_CREATURE = 0,          //done
    SMART_SCRIPT_TYPE_GAMEOBJECT = 1,          //done
    SMART_SCRIPT_TYPE_AREATRIGGER = 2,          //done
    SMART_SCRIPT_TYPE_EVENT = 3,          //
    SMART_SCRIPT_TYPE_GOSSIP = 4,          //
    SMART_SCRIPT_TYPE_QUEST = 5,          //
    SMART_SCRIPT_TYPE_SPELL = 6,          //
    SMART_SCRIPT_TYPE_TRANSPORT = 7,          //
    SMART_SCRIPT_TYPE_INSTANCE = 8,          //
    SMART_SCRIPT_TYPE_TIMED_ACTIONLIST = 9,          //
    SMART_SCRIPT_TYPE_MAX = 10
};

enum SmartAITypeMaskId
{
    SMART_SCRIPT_TYPE_MASK_CREATURE = 1, SMART_SCRIPT_TYPE_MASK_GAMEOBJECT = 2, SMART_SCRIPT_TYPE_MASK_AREATRIGGER = 4, SMART_SCRIPT_TYPE_MASK_EVENT = 8, SMART_SCRIPT_TYPE_MASK_GOSSIP = 16, SMART_SCRIPT_TYPE_MASK_QUEST = 32, SMART_SCRIPT_TYPE_MASK_SPELL = 64, SMART_SCRIPT_TYPE_MASK_TRANSPORT = 128, SMART_SCRIPT_TYPE_MASK_INSTANCE = 256, SMART_SCRIPT_TYPE_MASK_TIMED_ACTIONLIST = 512,
};

const uint32 SmartAITypeMask[SMART_SCRIPT_TYPE_MAX][2] =
{
{ SMART_SCRIPT_TYPE_CREATURE, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_SCRIPT_TYPE_GAMEOBJECT, SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_SCRIPT_TYPE_AREATRIGGER, SMART_SCRIPT_TYPE_MASK_AREATRIGGER },
{ SMART_SCRIPT_TYPE_EVENT, SMART_SCRIPT_TYPE_MASK_EVENT },
{ SMART_SCRIPT_TYPE_GOSSIP, SMART_SCRIPT_TYPE_MASK_GOSSIP },
{ SMART_SCRIPT_TYPE_QUEST, SMART_SCRIPT_TYPE_MASK_QUEST },
{ SMART_SCRIPT_TYPE_SPELL, SMART_SCRIPT_TYPE_MASK_SPELL },
{ SMART_SCRIPT_TYPE_TRANSPORT, SMART_SCRIPT_TYPE_MASK_TRANSPORT },
{ SMART_SCRIPT_TYPE_INSTANCE, SMART_SCRIPT_TYPE_MASK_INSTANCE },
{ SMART_SCRIPT_TYPE_TIMED_ACTIONLIST, SMART_SCRIPT_TYPE_MASK_TIMED_ACTIONLIST } };

const uint32 SmartAIEventMask[SMART_EVENT_END][2] =
{
{ SMART_EVENT_UPDATE_IC, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_TIMED_ACTIONLIST },
{ SMART_EVENT_UPDATE_OOC, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT + SMART_SCRIPT_TYPE_MASK_INSTANCE },
{ SMART_EVENT_HEALT_PCT, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_MANA_PCT, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_AGGRO, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_KILL, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_DEATH, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_EVADE, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_SPELLHIT, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_RANGE, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_OOC_LOS, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_RESPAWN, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_TARGET_HEALTH_PCT, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_TARGET_CASTING, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_FRIENDLY_HEALTH, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_FRIENDLY_IS_CC, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_FRIENDLY_MISSING_BUFF, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_SUMMONED_UNIT, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_TARGET_MANA_PCT, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_ACCEPTED_QUEST, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_REWARD_QUEST, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_REACHED_HOME, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_RECEIVE_EMOTE, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_HAS_AURA, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_TARGET_BUFFED, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_RESET, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_IC_LOS, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_PASSENGER_BOARDED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_PASSENGER_REMOVED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_CHARMED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_CHARMED_TARGET, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_SPELLHIT_TARGET, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_DAMAGED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_DAMAGED_TARGET, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_MOVEMENTINFORM, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_SUMMON_DESPAWNED, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_CORPSE_REMOVED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_AI_INIT, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_DATA_SET, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_WAYPOINT_START, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_WAYPOINT_REACHED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_TRANSPORT_ADDPLAYER, SMART_SCRIPT_TYPE_MASK_TRANSPORT },
{ SMART_EVENT_TRANSPORT_ADDCREATURE, SMART_SCRIPT_TYPE_MASK_TRANSPORT },
{ SMART_EVENT_TRANSPORT_REMOVE_PLAYER, SMART_SCRIPT_TYPE_MASK_TRANSPORT },
{ SMART_EVENT_TRANSPORT_RELOCATE, SMART_SCRIPT_TYPE_MASK_TRANSPORT },
{ SMART_EVENT_INSTANCE_PLAYER_ENTER, SMART_SCRIPT_TYPE_MASK_INSTANCE },
{ SMART_EVENT_AREATRIGGER_ONTRIGGER, SMART_SCRIPT_TYPE_MASK_AREATRIGGER },
{ SMART_EVENT_QUEST_ACCEPTED, SMART_SCRIPT_TYPE_MASK_QUEST },
{ SMART_EVENT_QUEST_OBJ_COPLETETION, SMART_SCRIPT_TYPE_MASK_QUEST },
{ SMART_EVENT_QUEST_REWARDED, SMART_SCRIPT_TYPE_MASK_QUEST },
{ SMART_EVENT_QUEST_COMPLETION, SMART_SCRIPT_TYPE_MASK_QUEST },
{ SMART_EVENT_QUEST_FAIL, SMART_SCRIPT_TYPE_MASK_QUEST },
{ SMART_EVENT_TEXT_OVER, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_RECEIVE_HEAL, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_JUST_SUMMONED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_WAYPOINT_PAUSED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_WAYPOINT_RESUMED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_WAYPOINT_STOPPED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_WAYPOINT_ENDED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_TIMED_EVENT_TRIGGERED, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_UPDATE, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_LINK, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT + SMART_SCRIPT_TYPE_MASK_AREATRIGGER + SMART_SCRIPT_TYPE_MASK_EVENT + SMART_SCRIPT_TYPE_MASK_GOSSIP + SMART_SCRIPT_TYPE_MASK_QUEST + SMART_SCRIPT_TYPE_MASK_SPELL + SMART_SCRIPT_TYPE_MASK_TRANSPORT + SMART_SCRIPT_TYPE_MASK_INSTANCE },
{ SMART_EVENT_GOSSIP_SELECT, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_JUST_CREATED, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_GOSSIP_HELLO, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{ SMART_EVENT_FOLLOW_COMPLETED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_DUMMY_EFFECT, SMART_SCRIPT_TYPE_MASK_CREATURE },
{ SMART_EVENT_IS_BEHIND_TARGET, SMART_SCRIPT_TYPE_MASK_CREATURE } };

enum SmartEventFlags
{
    SMART_EVENT_FLAG_NOT_REPEATABLE = 0x01,          //Event can not repeat
    SMART_EVENT_FLAG_DIFFICULTY_0 = 0x02,          //Event only occurs in instance difficulty 0
    SMART_EVENT_FLAG_DIFFICULTY_1 = 0x04,          //Event only occurs in instance difficulty 1
    SMART_EVENT_FLAG_DIFFICULTY_2 = 0x08,          //Event only occurs in instance difficulty 2
    SMART_EVENT_FLAG_DIFFICULTY_3 = 0x10,          //Event only occurs in instance difficulty 3
    SMART_EVENT_FLAG_RESERVED_5 = 0x20, SMART_EVENT_FLAG_RESERVED_6 = 0x40, SMART_EVENT_FLAG_DEBUG_ONLY = 0x80,          //Event only occurs in debug build

    SMART_EVENT_FLAG_DIFFICULTY_ALL = (SMART_EVENT_FLAG_DIFFICULTY_0 | SMART_EVENT_FLAG_DIFFICULTY_1 | SMART_EVENT_FLAG_DIFFICULTY_2 | SMART_EVENT_FLAG_DIFFICULTY_3)
};

enum SmartCastFlags
{
    SMARTCAST_INTERRUPT_PREVIOUS = 0x01,          //Interrupt any spell casting
    SMARTCAST_TRIGGERED = 0x02,
//Triggered (this makes spell cost zero mana and have no cast time)
//CAST_FORCE_CAST             = 0x04,                     //Forces cast even if creature is out of mana or out of range
//CAST_NO_MELEE_IF_OOM        = 0x08,                     //Prevents creature from entering melee if out of mana or out of range
//CAST_FORCE_TARGET_SELF      = 0x10,                     //Forces the target to cast this spell on itself
//CAST_AURA_NOT_PRESENT       = 0x20,                     //Only casts the spell if the target does not have an aura from the spell
};

// one line in DB is one event
struct SmartScriptHolder
{
    SmartScriptHolder()
    {
        timer = 0;
        active = false;
        runOnce = false;
        link = 0;
        entryOrGuid = 0;
        link = 0;
        event_id = 0;
        enableTimed = false;
    }
    int32 entryOrGuid;
    SmartScriptType source_type;
    uint32 event_id;
    uint32 link;

    SmartEvent event;
    SmartAction action;
    SmartTarget target;

public:
    uint32 GetScriptType() const
    {
        return (uint32) source_type;
    }
    uint32 GetEventType() const
    {
        return (uint32) event.type;
    }
    uint32 GetActionType() const
    {
        return (uint32) action.type;
    }
    uint32 GetTargetType() const
    {
        return (uint32) target.type;
    }

    uint32 timer;
    bool active;
    bool runOnce;
    bool enableTimed;
};

typedef UNORDERED_MAP<uint32, WayPoint*> WPPath;

typedef std::list<WorldObject*> ObjectList;
typedef UNORDERED_MAP<uint32, ObjectList*> ObjectListMap;

class SmartWaypointMgr
{
    friend class ACE_Singleton<SmartWaypointMgr, ACE_Null_Mutex> ;
    SmartWaypointMgr()
    {
    }
    ;
public:
    ~SmartWaypointMgr()
    {
    }
    ;

    void LoadFromDB();

    WPPath* GetPath(uint32 id)
    {
        if (waypoint_map.find(id) != waypoint_map.end())
            return waypoint_map[id];
        else
            return 0;
    }

private:
    UNORDERED_MAP<uint32, WPPath*> waypoint_map;
};

// all events for a single entry
typedef std::vector<SmartScriptHolder> SmartAIEventList;

// all events for all entries / guids
typedef UNORDERED_MAP<int32, SmartAIEventList> SmartAIEventMap;

class SmartAIMgr
{
    friend class ACE_Singleton<SmartAIMgr, ACE_Null_Mutex> ;
    SmartAIMgr()
    {
    }
    ;
public:
    ~SmartAIMgr()
    {
    }
    ;

    void LoadSmartAIFromDB();

    SmartAIEventList GetScript(int32 entry, SmartScriptType type)
    {
        SmartAIEventList temp;
        if (mEventMap[uint32(type)].find(entry) != mEventMap[uint32(type)].end())
            return mEventMap[uint32(type)][entry];
        else
        {
            if (entry > 0)          //first search is for guid (negative), do not drop error if not found
                sLog->outDebug(LOG_FILTER_TSCR, "SmartAIMgr::GetScript: Could not load Script for Entry %d ScriptType %u.", entry, uint32(type));
            return temp;
        }
    }

private:
    //event stores
    SmartAIEventMap mEventMap[SMART_SCRIPT_TYPE_MAX];

    bool IsEventValid(SmartScriptHolder &e);
    bool IsTargetValid(SmartScriptHolder e);
    /*inline bool IsTargetValid(SmartScriptHolder e, int32 target)
     {
     if (target < SMART_TARGET_NONE || target >= SMART_TARGET_END)
     {
     sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses invalid Target type %d, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), target);
     return false;
     }
     return true;
     }*/
    inline bool IsMinMaxValid(SmartScriptHolder e, uint32 min, uint32 max)
    {
        if (max < min)
        {
            sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses min/max params wrong (%u/%u), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), min, max);
            return false;
        }
        return true;
    }
    /*inline bool IsPercentValid(SmartScriptHolder e, int32 pct)
     {
     if (pct < -100 || pct > 100)
     {
     sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u has invalid Percent set (%d), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), pct);
     return false;
     }
     return true;
     }*/
    inline bool NotNULL(SmartScriptHolder e, uint32 data)
    {
        if (!data)
        {
            sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u Parameter can not be NULL, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
            return false;
        }
        return true;
    }
    inline bool IsCreatureValid(SmartScriptHolder e, uint32 entry)
    {
        if (!sCreatureStorage.LookupEntry<CreatureInfo>(entry))
        {
            sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Creature entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
            return false;
        }
        return true;
    }
    inline bool IsQuestValid(SmartScriptHolder e, uint32 entry)
    {
        if (!sObjectMgr->GetQuestTemplate(entry))
        {
            sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Quest entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
            return false;
        }
        return true;
    }
    inline bool IsGameObjectValid(SmartScriptHolder e, uint32 entry)
    {
        if (!sGOStorage.LookupEntry<GameObjectInfo>(uint32(entry)))
        {
            sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent GameObject entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
            return false;
        }
        return true;
    }
    inline bool IsSpellValid(SmartScriptHolder e, uint32 entry)
    {
        if (!sSpellStore.LookupEntry(entry))
        {
            sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Spell entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
            return false;
        }
        return true;
    }
    inline bool IsItemValid(SmartScriptHolder e, uint32 entry)
    {
        if (!sItemStore.LookupEntry(entry))
        {
            sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Item entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
            return false;
        }
        return true;
    }
    /*inline bool IsConditionValid(SmartScriptHolder e, int32 t, int32 v1, int32 v2, int32 v3)
     {
     bool error = false;
     if (t > 0 && v1 >= 0 && v2 >= 0 && v3 >= 0)
     {
     Condition cond;
     cond.mConditionType = ConditionType(t);
     cond.mConditionValue1 = uint32(v1);
     cond.mConditionValue2 = uint32(v2);
     cond.mConditionValue3 = uint32(v3);
     if (!sConditionMgr->isConditionTypeValid(&cond))
     error = true;
     }
     if (error)
     {
     sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses invalid Condition, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
     return false;
     }
     return true;
     }*/
    inline bool IsTextEmoteValid(SmartScriptHolder e, uint32 entry)
    {
        if (!sEmotesTextStore.LookupEntry(entry))
        {
            sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Text Emote entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
            return false;
        }
        return true;
    }
    inline bool IsEmoteValid(SmartScriptHolder e, uint32 entry)
    {
        if (!sEmotesStore.LookupEntry(entry))
        {
            sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Emote entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
            return false;
        }
        return true;
    }
    inline bool IsAreaTriggerValid(SmartScriptHolder e, uint32 entry)
    {
        if (!sAreaTriggerStore.LookupEntry(entry))
        {
            sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent AreaTrigger entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
            return false;
        }
        return true;
    }
    inline bool IsSoundValid(SmartScriptHolder e, uint32 entry)
    {
        if (!sSoundEntriesStore.LookupEntry(entry))
        {
            sLog->outErrorDb("SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Sound entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry);
            return false;
        }
        return true;
    }
    bool IsTextValid(SmartScriptHolder e, uint32 id);
};

#define sSmartScriptMgr ACE_Singleton<SmartAIMgr, ACE_Null_Mutex>::instance()
#define sSmartWaypointMgr ACE_Singleton<SmartWaypointMgr, ACE_Null_Mutex>::instance()
#endif
